<?php
/**
 *
 *
 *
 */
class Yz_Form_Element_Select
    extends Yz_Form_Element_Abstract
    implements Yz_Form_Element_Interface
{

    protected $element;
    protected $name;
    protected $options;
    protected $value;

    /**
     *  @param Traversable elements: [name: params]
     *      Params are passed to element constructor
     *  @param Yz_Property_Interface $element
     */
    public function __construct(
        Yz_Form_Interface $form,
        $name,
        Yz_Property_Interface $element=null
        )
    {
        parent::__construct( $form, $name, $element );
        $this->loadOptions();
        return;
    }


    public function render(Yz_Template_Interface $template)
    {
        $class = $this->getCSSClass();
        $options = $this->renderOptions($template);
        $o = <<<html
            <select name="{$this->name}" class="{$class}">
{$options}
            </select>\n
html;
        return $o;
    }


    /**
     *  @return this
     *  @throw Yz_Form_Element_Exception
     */
    public function parse(Yz_Hash $values)
    {
        $elName = $this->name;
        debug("Element '$elName'");
        /* ### it is superfluous
        if (! $values->offsetExists($elName)) {
            throw new Yz_Form_Element_Exception("Missing value for element {$elName}");
        }
        */
        $value = $values[$elName];
        $value = Yz_Int::valueOf($value);
        if (null === $value) {
            throw new Yz_Form_Element_Exception("Invalid value for element {$elName} (must be an integer number)");
        }
        if (0 === $value) {
            if ( ! $this->allowEmpty() ) {
                throw new Yz_Form_Element_Exception("Empty value for element {$elName}");
            }
        } else if (! $this->options->offsetExists($value)) {
            throw new Yz_Form_Element_Exception("Unrecognized value for element {$elName}");
        }
        $this->value = $value;
        return $this;
    }

    /**
     *
     *
     */
    protected function loadOptions()
    {
        debug();
        $element = $this->element;
        $moduleName = $element->moduleName;
        $modelName = $element->modelName;
        $module = $this->selectModule($moduleName);
        $model = $module->selectModel($modelName);
        $options = $model->fetchList();
        $this->options = $options;
        return $this;
    }

    protected function selectModule($moduleName)
    {
        debug();
        if (null === $moduleName) {
            $moduleName = $this->form->namespaceName() . '\\Module';
        }
        if (! class_exists($moduleName, false)) {
            throw new Yz_Exception("Failed to identify module class");
        }
        $module = $moduleName::getInstance();
        return $module;
    }

    /**
     *
     *
     */
    protected function renderOptions(Yz_Template_Interface $template)
    {
        debug();
        $o = "";
        $currentValue = (string)$this->value;
        if ($this->allowEmpty()) {
            $selected = $currentValue === 0 ? ' selected="selected"' : '';
            $text = $template->translate("-- Not selected --");
            $o .= <<<html
                    <option{$selected} value="0">{$text}</option>\n
html;
        }
        $options = $this->options;
        foreach ($options as $option) {
            $text = htmlspecialchars($option->title);
            $selected = $currentValue === $option->id ? ' selected="selected"' : '';
            $o .= <<<html
                    <option{$selected} value="{$option->id}">{$text}</option>\n
html;
        }
        return $o;
    }

}
